package com.giveu.signature.common.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.List;

import com.giveu.common.utils.HttpUtil;
import com.giveu.signature.bean.TemplateHtmlParam;
import com.giveu.signature.bean.TemplateHtmlParam.SignatureConf;
import com.giveu.signature.bean.TemplateHtmlParam.TemplateSign;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfSignatureAppearance.RenderingMode;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;

import okhttp3.HttpUrl;

public class PdfSignUtil {

	@SuppressWarnings("resource")
	public static void sign(String src, String target, TemplateHtmlParam thp) {
		String fileName = thp.getTempKey().replace(":", "_");
		InputStream inputStream = null;
		FileOutputStream outputStream = null;
		try {
			inputStream = new FileInputStream(src);
			outputStream = new FileOutputStream(target);
			PdfReader reader = new PdfReader(inputStream);
			List<TemplateSign> signList = thp.getTemplateSigns();
			for (TemplateSign templateSign : signList) {
				if(templateSign==null||templateSign.getSignConf()==null){
					continue;
				}
				SignatureConf sc = templateSign.getSignConf();
				String[] rect = templateSign.getRectangle().split(",");
				String imgPath = System.getProperty("java.io.tmpdir")+File.separator+"image"+File.separator
						+fileName+sc.getImageUrl().substring(sc.getImageUrl().lastIndexOf("."));
				if(!new File(imgPath).exists()){
					new File(imgPath).createNewFile();
					com.giveu.common.utils.FileUtil.download(sc.getImageUrl(), imgPath);
				}
				Image image = Image.getInstance(imgPath);
				if(sc.getSignFlag()==0){
					PdfStamper stamper = new PdfStamper(reader, outputStream);
					PdfContentByte under = stamper.getOverContent(1);
					image.setAbsolutePosition(Integer.parseInt(rect[0]),Integer.parseInt(rect[1]));
					image.scaleToFit(Integer.parseInt(rect[2]),Integer.parseInt(rect[3]));
					under.addImage(image);
					under.stroke();
					stamper.close();
				}else if(sc.getSignFlag()==1){
					PdfStamper stamper = PdfStamper.createSignature(reader, outputStream, '\0', null, true);
					PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
					appearance.setReason(templateSign.getReason());
					appearance.setLocation(templateSign.getLocation());
					appearance.setVisibleSignature(new Rectangle(Integer.parseInt(rect[0]),Integer.parseInt(rect[1]),
							Integer.parseInt(rect[2]),Integer.parseInt(rect[3])), templateSign.getPageNum(), templateSign.getFieldName());
					appearance.setSignatureGraphic(image);
					appearance.setCertificationLevel(sc.getCertificationLevel());
					appearance.setRenderingMode(getRenderingMode(sc.getRenderingMode()));
//					appearance.setCertificate(sc.getCertificate());
					KeyStore ks = KeyStore.getInstance(sc.getKeystoreType());
					String keyStorePath = System.getProperty("java.io.tmpdir")+File.separator+"keyStore"+File.separator
							+fileName+sc.getKeystoreUrl().substring(sc.getKeystoreUrl().lastIndexOf("."));
					if(!new File(keyStorePath).exists()){
						new File(keyStorePath).createNewFile();
						com.giveu.common.utils.FileUtil.download(sc.getKeystoreUrl(), keyStorePath);
					}
					char[] password = sc.getKeystorePassword().toCharArray();
		            ks.load(new FileInputStream(keyStorePath), password);
		            String alias = ks.aliases().nextElement();
		            PrivateKey pk = (PrivateKey) ks.getKey(alias, password);
		            // 得到证书链
		            Certificate[] chain = ks.getCertificateChain(alias);
					ExternalDigest digest = new BouncyCastleDigest();
					ExternalSignature signature = new PrivateKeySignature(pk, sc.getDigestAlgorithm(),null);
					MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0,getCryptoStandard(sc.getCryptoStandard()));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (null != outputStream) {
					outputStream.close();
				}
				if (null != inputStream) {
					inputStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static CryptoStandard getCryptoStandard(String cryptoStandard) {
		for (CryptoStandard cs : CryptoStandard.values()) {
			if(cs.name().equals(cryptoStandard)){
				return cs;
			}
		}
		return CryptoStandard.CMS;
	}

	private static RenderingMode getRenderingMode(String renderingMode) {
		for (RenderingMode cs : RenderingMode.values()) {
			if(cs.name().equals(renderingMode)){
				return cs;
			}
		}
		return RenderingMode.GRAPHIC;
	}
}
